/**
 * 2017年5月22日
 */
package cn.edu.bjtu.core;

import java.io.File;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;

import org.deeplearning4j.util.SerializationUtils;
import org.nd4j.linalg.api.ndarray.INDArray;

import cn.edu.bjtu.configuration.TextCategorizationCNNConfig;

/**
 * 类标名称管理器
 * 一个网络输出的结果应该是一个向量,(向量长度应该与这个类里面labels里面元素个数相相等,所以训练网络的时候需要更新这里面的数据.)
 * 这个向量代表了每个类的概率
 * 每个类名是什么
 * 就是用这个类来对应上
 * 
 * 对于这个类可能比较麻烦的一点就是 单例与序列化之间的矛盾
 * 
 * 因为单例保证JVM中只有一个实例,但是序列化可以打破这个规定
 * 所以注意readResolve方法及restore方法
 * 
 * @author Alex
 *
 */
public class TextCategorizationManager extends LoggerSupport implements Serializable {
	private static final long serialVersionUID = 1808091468086231953L;
	/*private final Map<String,TextCategorization> classMapRealtion ;
	private enum TextCategorization{
		POLITICS_MILITARY(1,"政治军事"),
		CULTURAL_RELIGION(2, "文化宗教"),
		FASHION_DESIGN(3, "时尚设计"),
		EDUCATION(4, "教育"),
		BABYSITTER(5, "育儿"),
		AGRICULTURAL_ENVIRONMENT(6, "农业环境"),
		LIFE(7,"生活"),
		SOCIETY(8,"社会"),
		TECHNOLOGY(9,"科技"),
		PHYSICAL_ENTERTAINMENT(10,"体育娱乐"),
		ENERGY_ESTATE(11,"能源地产"),
		TOURISM(12,"旅游"),
		FINANCE(13,"财经"),
		AD(14,"广告"),
		OHTER(15,"其它");
		private TextCategorization(int idx,String desc){
			this.idx= idx;
			this.chineseLiteral = desc;
		}
		private int idx;
		private String chineseLiteral;
		
	}*/
	
	public static final class ClassificationPair {
		private final String cate;
		private final double val;
		public ClassificationPair(String cate,double val) {
			this.cate = cate;
			this.val = val;
		}
		
		public String toString(){
			return "{label:"+cate+","+"val:"+val+"}";
		}
		
		public String getLabelName() {
			return cate;
		}
		public double getVal() {
			return val;
		}
		
		
	}
	
	private static TextCategorizationManager inst = null;
	private TextCategorizationManager(){
//		Map<String, TextCategorization> map = new HashMap<String,TextCategorization>();
//		map.put("1", 	TextCategorization.POLITICS_MILITARY);
//		map.put("2", 	TextCategorization.CULTURAL_RELIGION);
//		map.put("3", 	TextCategorization.FASHION_DESIGN);
//		map.put("4", 	TextCategorization.EDUCATION);
//		map.put("5", 	TextCategorization.BABYSITTER);
//		map.put("6", 	TextCategorization.AGRICULTURAL_ENVIRONMENT);
//		map.put("7", 	TextCategorization.LIFE);
//		map.put("8", 	TextCategorization.SOCIETY);
//		map.put("9", 	TextCategorization.TECHNOLOGY);
//		map.put("10",	TextCategorization.PHYSICAL_ENTERTAINMENT);
//		map.put("11", 	TextCategorization.ENERGY_ESTATE);
//		map.put("12", 	TextCategorization.TOURISM);
//		map.put("13", 	TextCategorization.FINANCE);
//		map.put("14", 	TextCategorization.AD);
//		map.put("15", 	TextCategorization.OHTER);
//		classMapRealtion = Collections.<String,TextCategorization>unmodifiableMap(map);
	};
	
	private List<String> labels;
	
	public synchronized TextCategorizationManager setLabels(List<String> labels){
		this.labels = new ArrayList<String>(labels);
		return this;
	}
	public synchronized TextCategorizationManager saveLabels(){
		try{
			SerializationUtils.saveObject(this, new File(TextCategorizationCNNConfig.get().getLabelsFile()));
		}catch(Exception e){
			logException(e);
		}
		return this;
	}
	
	public static synchronized TextCategorizationManager restore(){
		try{
			TextCategorizationManager tcm = SerializationUtils.<TextCategorizationManager>readObject(new File(TextCategorizationCNNConfig.get().getLabelsFile()));
			if(inst==null) inst = tcm;
			if(inst.labels == null){
				inst.labels = tcm.labels;
			}
			return inst;
		}catch(Exception e){
			e.printStackTrace();
		}
		return inst;
	}
	
	public ClassificationPair[] getDesc(INDArray arr){
		ClassificationPair res [] = new ClassificationPair[this.labels.size()];
		for(int i=0;i<res.length;i++){
			res[i] = new ClassificationPair(this.labels.get(i), arr.getDouble(i));
		}
		Arrays.<ClassificationPair>sort(res,(x,y)->{
			double t = y.val-x.val;
			return t>0?1:(t<0?-1:0);
		});
		return res;
	}
	public boolean checkLabel(String label){
		return this.labels.contains(label);
	}
	
	public static TextCategorizationManager get(){
		if(inst == null){
			synchronized (TextCategorizationManager.class) {
				if(inst == null){
					inst =  new TextCategorizationManager();
				}
			}
		}
		return inst;
	}
	public static void main(String args[]){
		List<String >lables = new ArrayList<>();
		File fs[] = new File("D:\\Share\\answer").listFiles();
		for(File f:fs){
			lables.add(f.getName());
		}
		Collections.sort(lables);
		TextCategorizationManager.get().setLabels(lables).saveLabels();
		
		System.out.println(TextCategorizationManager.get() ==TextCategorizationManager.restore());
		System.out.println(TextCategorizationManager.restore().inst.labels);
		
		
		
//		System.out.println(TextCategorizationManager.get() == );
//		System.out.println(TextCategorizationManager.get().labels);
		
	}
	
}

//Map<String, String> map = new HashMap<String,String>();
//map.put("1", "政治军事");
//map.put("2", "文化宗教");
//map.put("3", "时尚设计");
//map.put("4", "教育");
//map.put("5", "育儿");
//map.put("6", "农业环境");
//map.put("7", "生活");
//map.put("8", "社会");
//map.put("9", "科技");
//map.put("10", "体育娱乐");
//map.put("11", "能源地产");
//map.put("12", "旅游");
//map.put("13", "财经");
//map.put("14", "广告");
//map.put("15", "其他");
//classMapRealtion = Collections.<String,String>unmodifiableMap(map);
